package org.safaproject.data.dao.jpa;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Example;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import org.springframework.transaction.annotation.Transactional;

import org.safaproject.data.dao.interfaces.Dao;
import org.safaproject.data.dataobjects.DomainObject;

public abstract class AbstractDaoJPAImpl<T extends DomainObject> extends
		JpaDaoSupport implements Dao<T> {

	@PersistenceContext
	private EntityManager em;
	private Class<T> domainClass;

	public AbstractDaoJPAImpl(Class<T> domainClass) {
		this.domainClass = domainClass;
	}

	@Transactional
	public void delete(T object) {
		getJpaTemplate().remove(object);
	}

	@Transactional
	public T load(Serializable id) {
		return getJpaTemplate().find(domainClass, id);
	}

	@Transactional
	public T save(T object) {
		return getJpaTemplate().merge(object);
	}

	@SuppressWarnings("unchecked")
	@Transactional
	public List<T> findByExample(final T exampleInstance) {
		Example example = Example.create(exampleInstance).excludeZeroes()
				.ignoreCase().enableLike();
		DetachedCriteria criteria = DetachedCriteria.forClass(exampleInstance.getClass());
		criteria.add(example);
		
		Session session = (Session) em.getDelegate();
		Criteria crit = session.createCriteria(exampleInstance.getClass());
		final List<T> result = crit.list();
		return result;
	}

}
